/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package game;

import game.chips.Color;
import game.ThreadPool;
import game.writer.*;
import java.io.IOException;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;

import org.apache.log4j.Logger;


public class Game implements Runnable{
    private static final Logger log = Logger.getLogger("logfile");

    private ExecutorService exec = Executors.newFixedThreadPool(2);
    
    private List<Player> players;
    
    private final static AtomicInteger gameNum = new AtomicInteger(0);
    
    private final int curGame = gameNum.incrementAndGet();
    
    private final static int GAME_SIZE = 5;
    private final static int CHIP_LINES = 2;
    
    private AtomicInteger turn = new AtomicInteger(0);
    private AtomicBoolean end = new AtomicBoolean(false);
    private AtomicBoolean end_turn = new AtomicBoolean(false);
    
    private Writer writer;
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        //Game game = new Game();
        //game.start();
        
        for (int i = 0; i < 1; i++) {
            try {
                ThreadPool.getPool().execute(new Game());
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        ThreadPool.getPool().shutdown();
    }
    
    public void run() {
        start();
        //log.warn("Game " + curGame + " is end.");
    }
    
    public Game() throws IOException {
        writer = new ConsoleWriter();
        //writer = new FileWrite("C:\\Logs\\gamelog\\" + this.toString() + ".txt");
        players = new ArrayList<Player>();
        players.add(new Player(this , Color.WHITE));
        players.add(new Player(this , Color.BLACK));
        
    }
    
    private AtomicBoolean hasBeenRun = new AtomicBoolean(false);
    
    public void start() {
        if (!hasBeenRun.compareAndSet(false, true))
            return;
        
        players.get(0).nextTurn();
        
        while(!end.get()) {
            try {
                if(end_turn.get()) {
                    paced();
                } else
                    Thread.sleep(10);
            } catch (InterruptedException e) {
                writer.print("Some problem");
            } 
        }
        
    }
    
    public void paced() {
        end_turn.compareAndSet(true, false);
        
        Step step = (turn.get() == 0 ? new Step(players.get(0), players.get(1)) : new Step(players.get(1), players.get(0)));
        
        step.doStep();
        
        for (Player player : players)
            player.updateChips();
        
        if (step.isLastStep()) {
            end.compareAndSet(false, true);
            writer.print("Final score: ");
            log.warn("Final score: ");
            printScore();
            exec.shutdownNow();
            return;
        }
        printScore();
        
        if (turn.get() == 0) {
            turn.compareAndSet(0, 1);
            players.get(1).nextTurn();
        } else {
            turn.compareAndSet(1, 0);
            players.get(0).nextTurn();
        }
    }
    
    public int getTurn() { return turn.get(); }
    public List<Player> getPlayers() { return players; }
    public static int getSize() { return GAME_SIZE; }
    public static int getChipLines() { return CHIP_LINES; }
    public boolean isEnd() { return end.get(); }
    
    public void startPlayer(Player player) {
        exec.execute(player);
    }
    
    public void checkGame() { end_turn.compareAndSet(false, true); }
    public void printScore() { 
        log.warn(players.get(0).getCountChips() + " : " + players.get(1).getCountChips()); 
        writer.print(players.get(0).getCountChips() + " : " + players.get(1).getCountChips());
    }
    
    public Writer getWriter () { return writer; }
    
    public String toString() {
        return ("Game#" + curGame + " ");
    }
}
